const router = require("koa-router")();
const path = require("path");
const fse = require("fs-extra");
const spath = path.resolve(process.cwd(), "public", "file");
const { file } = require("../models/index");
const { url } = require("../utils/url");
const remove = (folderPath) => {
  return new Promise(async (resolve, reject) => {
    try {
      await fse.remove(folderPath);
      resolve(1);
    } catch (error) {
      reject(0);
    }
  });
};

const saveFileInfo = async (hash, name, cindex, hz, max) => {
  try {
    let res = await file.findOne({ hash: hash });

    if (!res) {
      await file.create({
        hash: hash,
        name: name,
        cindex: cindex,
        hz: hz,
        max: max,
        url: url + hash + "--" + name + "." + hz,
      });
    } else {
      await file.findOneAndUpdate(
        { hash: hash }, // 查询条件
        { $set: { cindex: cindex } }, // 更新操作
        { returnDocument: "after" } // 返回修改后的文档
      );
    }
  } catch (error) {
    console.log(error, "error");
  }
};

router.post("/", async (ctx, next) => {
  try {
    let fileInfo = ctx.request.files.file;
    let max = ctx.request.body.sliceMax;
    // "文件唯一hash//文件名--hashIndex||后缀"
    const fileNameArr = fileInfo.originalFilename.split("||");
    let name = fileNameArr[0].split("//")[1].split("--")[0];
    let index = fileNameArr[0].split("--")[1];
    let hash = fileNameArr[0].split("//")[0];
    let hz = fileNameArr[1];
    // 存放切片的目录
    const chunkDir = `${spath}/${name}`;
    // return
    if (!fse.existsSync(chunkDir)) {
      // 创建大文件的临时目录
      try {
        await fse.mkdirs(chunkDir);
      } catch (error) {
        console.log(error);
      }
    }
    // 原文件名.index - 每个分片的具体地址和名字
    const dPath = path.join(spath, hash + "--" + name, index);
    // 将分片文件从 temp 中移动到本次上传大文件的临时目录
    await fse.move(fileInfo.filepath, dPath, { overwrite: true });
    const fileIndexDir = path.join(spath, hash + "--" + name);
    const chunks = await fse.readdir(fileIndexDir);
    let cindex = chunks.length;

    saveFileInfo(hash, name, cindex, hz, max);

    ctx.body = {
      code: 200,
      msg: `切片${cindex}/${max}上传成功`,
    };
  } catch (error) {
    ctx.body = {
      code: 201,
      msg: JSON.stringify(error),
    };
  }
});

//断点传续 通过搜索目录到底几个返回给前端 前端从那个开始重新上传合并
router.get("/reload", async (ctx, next) => {
  const { hash, name } = ctx.request.query;
  const fileIndexDir = path.join(spath, hash + "--" + name);
  const chunks = await fse.readdir(fileIndexDir);
  const findFirstDiscontinuousIndex = (arr) => {
    arr.sort((a, b) => a - b); // 首先对数组进行排序
    console.log(arr, "arr");
    if (+arr[0] !== 0) {
      return -2; // 如果第一个不是0就有问题
    }
    for (let i = 0; i < arr.length - 1; i++) {
      if (+arr[i + 1] - +arr[i] > 1) {
        return i + 1; // 找到第一个不连续的数字的下标并返回
      }
    }
    return -1; // 如果没有不连续的数字则返回-1
  };

  let indexRes = findFirstDiscontinuousIndex(chunks);

  if (indexRes === -1) {
    console.log("正常");

    try {
      let res = await file.findOne({ hash: hash });
      if (res.cindex !== chunks.length) {
        await file.findOneAndUpdate(
          { hash: hash },
          { $set: { cindex: chunks.length } },
          { returnDocument: "after" }
        );
        ctx.body = {
          code: 200,
          msg: "success",
          data: {
            index: chunks.length,
            hash: res.hash,
            name: res.name,
            hz: res.hz,
            max: res.max,
          },
        };
      } else {
        ctx.body = {
          code: 200,
          msg: "success",
          data: {
            index: res.cindex,
            hash: res.hash,
            name: res.name,
            hz: res.hz,
            max: res.max,
          },
        };
      }
    } catch (error) {
      ctx.body = {
        code: 201,
        msg: JSON.stringify(error),
      };
    }
  } else if (indexRes === -2) {
    let res = await file.findOneAndUpdate(
      { hash: hash },
      { $set: { cindex: 0 } },
      { returnDocument: "after" }
    );
    console.log("第一个有问题");
    ctx.body = {
      code: 200,
      msg: "success",
      data: {
        index: 0,
        hash: res.hash,
        name: res.name,
        hz: res.hz,
        max: res.max,
      },
    };
  } else {
    console.log(`第${indexRes}个有问题`);
    try {
      let res = await file.findOneAndUpdate(
        { hash: hash },
        { $set: { cindex: indexRes } },
        { returnDocument: "after" }
      );
      ctx.body = {
        code: 200,
        msg: "success",
        data: {
          index: indexRes,
          hash: res.hash,
          name: res.name,
          hz: res.hz,
          max: res.max,
        },
      };
    } catch (error) {
      console.log(error, "error");
      ctx.body = {
        code: 201,
        msg: JSON.stringify(error),
      };
    }
  }
});
router.get("/file", async (ctx, next) => {
  await ctx.render("index");
});
router.get("/merge", async (ctx, next) => {
  var url = "";
  const apath = path.resolve(process.cwd(), "public");
  try {
    const { name } = ctx.request.query;
    const fhname = name.split("||")[0];
    const fname = name.split("||")[0].split("--")[1];
    const hz = name.split("||")[1];
    const chunkDir = path.join(spath, fhname);
    const chunks = await fse.readdir(chunkDir);
    const removeDir = `${spath}/${fname}`;
    chunks
      .sort((a, b) => a - b)
      .map((chunkPath) => {
        // 合并文件
        fse.appendFileSync(
          path.join(apath, "upload", fhname + "." + hz),
          fse.readFileSync(`${chunkDir}/${chunkPath}`)
        );
        fse.remove(removeDir, (err) => {
          if (err) console.log(err);
        });
      });
    url = `${fhname + "." + hz}`;
    ctx.body = {
      code: 200,
      msg: "上传成功",
      data: url,
    };
    // 返回文件地址
  } catch (error) {
    console.log(error);
    ctx.body = {
      code: 201,
      msg: JSON.stringify(error),
    };
  }
});
router.get("/getFileInfo", async (ctx, next) => {
  try {
    let res = await file.find();
    ctx.body = {
      code: 200,
      msg: "success",
      data: res,
    };
  } catch (error) {
    ctx.body = {
      code: 201,
      msg: JSON.stringify(error),
    };
  }
});

const delFile = (hash) => {
  return new Promise(async (resolve, reject) => {
    try {
      await file.findOneAndDelete({
        hash: hash,
      });
      resolve(1);
    } catch (error) {
      console.log(error);
      reject(JSON.stringify(error));
    }
  });
};

router.post("/removeFile", async (ctx, next) => {
  let hash = ctx.request.body.hash;
  try {
    await delFile(hash);
    ctx.body = {
      code: 200,
      msg: "success",
    };
  } catch (error) {
    console.log(error);
    ctx.body = {
      code: 201,
      msg: JSON.stringify(error),
    };
  }
});

router.post("/removeDir", async (ctx, next) => {
  let hash = ctx.request.body.hash;
  let name = ctx.request.body.name;
  let hz = ctx.request.body.hz;
  let aDir = path.resolve(process.cwd(), "public", "file", hash + "--" + name);
  let cDir = path.resolve(process.cwd(), "public", "file", name);
  let bDir = path.resolve(
    process.cwd(),
    "public",
    "upload",
    hash + "--" + name + "." + hz
  );
  let ares = await remove(aDir);
  let bres = await remove(bDir);
  let cres = await remove(cDir);
  if (ares === 1 && bres === 1) {
    try {
      await delFile(hash);
      ctx.body = {
        code: 200,
        msg: "文件删除成功",
      };
    } catch (error) {
      console.log(error);
      ctx.body = {
        code: 201,
        msg: JSON.stringify(error),
      };
    }
  } else {
    let msg = "";
    if (ares === 0) {
      msg += "file文件删除异常";
    }
    if (bres === 0) {
      msg += "upload文件删除异常";
    }
    ctx.body = {
      code: 201,
      msg: msg,
    };
  }
});

module.exports = router;
